// Commands.cpp : implementation file
//

#include "stdafx.h"
#include "PBAddin.h"
#include "Commands.h"
#include "Helper.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CCommands

CCommands::CCommands()
{
	m_pApplication = NULL;
	m_pApplicationEventsObj = NULL;
	m_pDebuggerEventsObj = NULL;
}

CCommands::~CCommands()
{
	ASSERT (m_pApplication != NULL);
	m_pApplication->Release();
}

void CCommands::SetApplicationObject(IApplication* pApplication)
{
	// This function assumes pApplication has already been AddRef'd
	//  for us, which CPBAddIn did in its QueryInterface call
	//  just before it called us.
	m_pApplication = pApplication;

	// Create Application event handlers
	XApplicationEventsObj::CreateInstance(&m_pApplicationEventsObj);
	m_pApplicationEventsObj->AddRef();
	m_pApplicationEventsObj->Connect(m_pApplication);
	m_pApplicationEventsObj->m_pCommands = this;

	// Create Debugger event handler
	CComPtr<IDispatch> pDebugger;
	if (SUCCEEDED(m_pApplication->get_Debugger(&pDebugger)) 
		&& pDebugger != NULL)
	{
		XDebuggerEventsObj::CreateInstance(&m_pDebuggerEventsObj);
		m_pDebuggerEventsObj->AddRef();
		m_pDebuggerEventsObj->Connect(pDebugger);
		m_pDebuggerEventsObj->m_pCommands = this;
	}
}


void CCommands::UnadviseFromEvents()
{
	ASSERT (m_pApplicationEventsObj != NULL);
	m_pApplicationEventsObj->Disconnect(m_pApplication);
	m_pApplicationEventsObj->Release();
	m_pApplicationEventsObj = NULL;

	if (m_pDebuggerEventsObj != NULL)
	{
		// Since we were able to connect to the Debugger events, we
		//  should be able to access the Debugger object again to
		//  unadvise from its events (thus the VERIFY_OK below--see stdafx.h).
		CComPtr<IDispatch> pDebugger;
		VERIFY_OK(m_pApplication->get_Debugger(&pDebugger));
		ASSERT (pDebugger != NULL);
		m_pDebuggerEventsObj->Disconnect(pDebugger);
		m_pDebuggerEventsObj->Release();
		m_pDebuggerEventsObj = NULL;
	}
}


/////////////////////////////////////////////////////////////////////////////
// Event handlers

// TODO: Fill out the implementation for those events you wish handle
//  Use m_pCommands->GetApplicationObject() to access the Platform Builder
//  Application object

// Application events

HRESULT CCommands::XApplicationEvents::BeforeBuildStart()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::BuildFinish(long nNumErrors, long nNumWarnings)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::BeforeApplicationShutDown()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::DocumentOpen(IDispatch* theDocument)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::BeforeDocumentClose(IDispatch* theDocument)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::DocumentSave(IDispatch* theDocument)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::NewDocument(IDispatch* theDocument)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::WindowActivate(IDispatch* theWindow)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::WindowDeactivate(IDispatch* theWindow)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::WorkspaceOpen()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::WorkspaceClose()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::NewWorkspace()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::DownloadResult()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

// Debugger event
HRESULT CCommands::XDebuggerEvents::BreakpointHit(IDispatch* pBreakpoint)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}


/////////////////////////////////////////////////////////////////////////////
// CCommands methods

STDMETHODIMP CCommands::PBGenieCommandMethod() 
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	// TODO: Replace this with the actual code to execute this command
	//  Use m_pApplication to access the Platform Builder Application object,
	//  and VERIFY_OK to see error strings in DEBUG builds of your add-in
	//  (see stdafx.h)

	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
	::MessageBox(NULL, "  Enjoy!!!\n\nCreated by syuu", "PBGenie AddIns (free)", MB_OK | MB_ICONINFORMATION);	
	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));

	return S_OK;
}


/************************************************************************/
/*                                                                      */
/************************************************************************/
STDMETHODIMP CCommands::SwitchHCpp()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	ITextDocument* pDoc = GetDispatchProperty<ITextDocument*>
		(m_pApplication, _T("ActiveDocument"), IID_ITextDocument);
	if (pDoc)
	{
		CString strFullName = GetStringProperty(pDoc, _T("FullName"));
		pDoc->Release();

		CString strFullNameTmp;
		int nCount = 0;

		if (ExtensionIs(strFullName, _T("h")))
		{
			strFullNameTmp = ChangeFileExt(strFullName, _T("cpp"));

//////////////////////////////////////////////////////////////////////////
			if (FileExist(strFullNameTmp))
			{
				DoActivateDoc(strFullNameTmp);
				return S_OK;
			}

//  C:\proj\AddIns\VCGenie\include\VCGenie.cpp --> C:\proj\AddIns\VCGenie\VCGenie.cpp

			// include
			//strFullNameTmp = ChangeFileExt(strFullName, _T("cpp"));
			nCount = strFullNameTmp.Find(_T("\\include"));
			if (-1 != nCount)
			{
				strFullNameTmp.Replace(_T("\\include"), _T(""));
				if (FileExist(strFullNameTmp))
				{
					DoActivateDoc(strFullNameTmp);
					return S_OK;
				}
			}

			// publicinc
			strFullNameTmp = ChangeFileExt(strFullName, _T("cpp"));
			nCount = strFullNameTmp.Find(_T("\\publicinc"));
			if (-1 != nCount)
			{
				strFullNameTmp.Replace(_T("\\publicinc"), _T(""));
				if (FileExist(strFullNameTmp))
				{
					DoActivateDoc(strFullNameTmp);
					return S_OK;
				}
			}

			// groupinc
			strFullNameTmp = ChangeFileExt(strFullName, _T("cpp"));
			nCount = strFullNameTmp.Find(_T("\\groupinc"));
			if (-1 != nCount)
			{
				strFullNameTmp.Replace(_T("\\groupinc"), _T(""));
				if (FileExist(strFullNameTmp))
				{
					DoActivateDoc(strFullNameTmp);
					return S_OK;
				}
			}
		}
		else if (ExtensionIs(strFullName, _T("cpp")))
		{
			strFullNameTmp = ChangeFileExt(strFullName, _T("h"));

//////////////////////////////////////////////////////////////////////////
			if (FileExist(strFullNameTmp))
			{
				DoActivateDoc(strFullNameTmp);
				return S_OK;
			}

//	C:\proj\AddIns\VCGenie\VCGenie.h --> C:\proj\AddIns\VCGenie\include\VCGenie.h

			// include
			//strFullNameTmp = ChangeFileExt(strFullName, _T("h"));
			nCount = strFullNameTmp.ReverseFind(_T('\\'));
			strFullNameTmp.Insert(nCount, _T("\\include"));
			if (FileExist(strFullNameTmp))
			{
				DoActivateDoc(strFullNameTmp);
				return S_OK;
			}

			// publicinc
			strFullNameTmp = ChangeFileExt(strFullName, _T("h"));
			strFullNameTmp.Insert(nCount, _T("\\publicinc"));
			if (FileExist(strFullNameTmp))
			{
				DoActivateDoc(strFullNameTmp);
				return S_OK;
			}

			// groupinc
			strFullNameTmp = ChangeFileExt(strFullName, _T("h"));
			strFullNameTmp.Insert(nCount, _T("\\groupinc"));
			if (FileExist(strFullNameTmp))
			{
				DoActivateDoc(strFullNameTmp);
				return S_OK;
			}
		}
	}
	else
	{
		//::MessageBox(::GetActiveWindow(), "Cannot Execute Command.\n\nNo Valid Text Document Is Opened.", "Error" ,MB_OK | MB_ICONINFORMATION);
	}

	return S_FALSE;
}


BOOL CCommands::FileExist(CString strFileName)
{
	CFileFind fFind;
	return fFind.FindFile(strFileName); 
}

void CCommands::DoActivateDoc(LPCTSTR FullName)
{
	USES_CONVERSION;

	// If already opened in Document List, then Activate it
	IDocuments* pDocs = GetDispatchProperty<IDocuments*>
		(m_pApplication, _T("Documents"), IID_IDocuments);
	bool bActived = false;
	if (pDocs)
	{
		long lCount = GetEnumCount(pDocs);
		for (long i=0; i<lCount; i++)
		{
			IGenericDocument* pDoc = GetEnumItem<IDocuments, IGenericDocument>
				(pDocs, i+1, IID_IGenericDocument);
			if (pDoc)
			{
				CString strFullName = GetStringProperty(pDoc, _T("FullName"));
				if (strFullName.CompareNoCase(FullName)==0)
				{
					pDoc->put_Active(VARIANT_TRUE);
					bActived = true;
				}
				pDoc->Release();
			}
			if (bActived) break;
		}

		if (!bActived)   // Not Found, open a new Document
		{
			LPDISPATCH pDisp = NULL;
			_variant_t varType(_T("Text"));
			_variant_t varReadOnly(false);
			CComBSTR bstrFullName(FullName);
			HRESULT hr = pDocs->Open(bstrFullName, varType, varReadOnly, &pDisp);
			if (SUCCEEDED(hr) && pDisp!=NULL)
			{
				IGenericDocument* pDoc = InterfaceAs<IGenericDocument>(pDisp, IID_IGenericDocument);
				if (pDoc)
				{
					pDoc->put_Active(VARIANT_TRUE);
					pDoc->Release();
				}
				pDisp->Release();
			}
		}
		pDocs->Release();
	}
}

/************************************************************************/
/*                                                                      */
/************************************************************************/



/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CCommands methods

STDMETHODIMP CCommands::CommentCode() 
{

	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));

	HRESULT hr ;

	hr = GetTextSelection(m_pApplication);
	if (!SUCCEEDED(hr))
	{
		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
		m_pTextselect = NULL;
		return E_FAIL;
	}

/*
	if(S_OK == JudgeCommentOrUncomment(m_pTextselect))
	{
		hr = UnCommentSelectedCode(m_pTextselect);
	}
	else 
	{
		hr = CommentSelectedCode(m_pTextselect);
	}
*/
	hr = CommentSelectedCode(m_pTextselect);


	if (!SUCCEEDED(hr))
	{
		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
		m_pTextselect = NULL;
		return E_FAIL;
	}

	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
	m_pTextselect = NULL;
	return S_OK;
}

HRESULT CCommands::GetTextSelection(IApplication *pApplication)
{
	HRESULT hr ;
	CComPtr<IDispatch> pActiveDocumentDisp;
	////////////////////////////
	hr = pApplication->get_ActiveDocument(&pActiveDocumentDisp);
	if (!SUCCEEDED(hr) || pActiveDocumentDisp == NULL)
		return E_FAIL;

	CComQIPtr<ITextDocument, &IID_ITextDocument> 
			pActiveDocument(pActiveDocumentDisp);

	if (pActiveDocument)
	{
		hr = pActiveDocument->get_Selection(&m_pTextselect);
		if (!SUCCEEDED(hr) || m_pTextselect == NULL)
			return E_FAIL;
	}
	else
		return E_FAIL;
	return S_OK;
}

HRESULT CCommands::CommentSelectedCode(IDispatch *pTextSel)
{
	long lTopLine = -1;
	long lBottomLine = -1;

	long iLine;
	CString s;
	CString ts;

	CComQIPtr<ITextSelection, &IID_ITextSelection> 
		pTextSelection(pTextSel);

	////////////////////////////
	HRESULT hr = pTextSelection->get_TopLine(&lTopLine);
	////////////////////////////
	hr = pTextSelection->get_BottomLine(&lBottomLine);
	_variant_t v((long)dsMove);
	////////////////////////////
	for(iLine = lTopLine; iLine <= lBottomLine; iLine++)
	{
		hr = pTextSelection->MoveTo(iLine, 1, v);
		if (SUCCEEDED(hr))
		{
			pTextSelection->SelectLine();
			BSTR bstrLineText;
			
			hr = pTextSelection->get_Text(&bstrLineText);
			if (SUCCEEDED(hr))
			{
				s = bstrLineText;
				ts = s;
				ts.TrimLeft();
				if (ts == "")
					continue;

//				if (ts.GetLength() < 2)
//				{
					s = _T("//") + s;
					pTextSelection->put_Text(s.AllocSysString());
//				}
//				else if (!(ts[0]=='/' && ts[1] =='/'))
//				{
//					if (s[0] == 0x20 && s[1] == 0x20)
//					{
//						s.SetAt(0, _T('/'));
//						s.SetAt(1, _T('/'));
//					}
//					else
//						s = _T("//") + s;
//					pTextSelection->put_Text(s.AllocSysString());
//				}
			}
		}
	}
	pTextSelection->Cancel();
	return S_OK;

}

STDMETHODIMP CCommands::UncommentCode()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
	
	HRESULT hr = GetTextSelection(m_pApplication);
	if (!SUCCEEDED(hr))
	{
		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
		m_pTextselect = NULL;
		return S_OK;
	}

	hr = UnCommentSelectedCode(m_pTextselect);
	if (!SUCCEEDED(hr))
	{
		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
		m_pTextselect = NULL;
		return E_FAIL;
	}

	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
	m_pTextselect = NULL;
	return S_OK;
}

HRESULT CCommands::UnCommentSelectedCode(IDispatch *pTextSel)
{
	long lTopLine = -1;
	long lBottomLine = -1;

	long iLine;
	CString s;
	CString ts;

	CComQIPtr<ITextSelection, &IID_ITextSelection> 
		pTextSelection(pTextSel);

	////////////////////////////
	HRESULT hr = pTextSelection->get_TopLine(&lTopLine);
	////////////////////////////
	hr = pTextSelection->get_BottomLine(&lBottomLine);
	_variant_t v((long)dsMove);
	////////////////////////////
	for(iLine = lTopLine; iLine <= lBottomLine; iLine++)
	{
		hr = pTextSelection->MoveTo(iLine, 1, v);
		if (SUCCEEDED(hr))
		{
			pTextSelection->SelectLine();
			BSTR bstrLineText;
			hr = pTextSelection->get_Text(&bstrLineText);
			if (SUCCEEDED(hr))
			{
				s = bstrLineText;
				ts = s;
				ts.TrimLeft();
				if (ts == "")
					continue;

				if (ts.GetLength() <2)
					continue ;

				if (ts[0]=='/' && ts[1] =='/')
				{
					int i = s.Find('/');
					s.Delete(i,2);
					pTextSelection->put_Text(s.AllocSysString());
				}
			}
		}
	}
	pTextSelection->Cancel();
	return S_OK;

}


//////////////////////////////////////////////////////////////
/*                            new                           */
//////////////////////////////////////////////////////////////
HRESULT CCommands::JudgeCommentOrUncomment(IDispatch *pTextSel)
{
	long lTopLine = -1;
	long lBottomLine = -1;

	long iLine;
	CString s;
	CString ts;

	CComQIPtr<ITextSelection, &IID_ITextSelection> 
		pTextSelection(pTextSel);

	////////////////////////////
	HRESULT hr = pTextSelection->get_TopLine(&lTopLine);
	////////////////////////////
	hr = pTextSelection->get_BottomLine(&lBottomLine);
	_variant_t v((long)dsMove);
	////////////////////////////
	for(iLine = lTopLine; iLine <= lBottomLine; iLine++)
	{
		hr = pTextSelection->MoveTo(iLine, 1, v);
		if (SUCCEEDED(hr))
		{
			pTextSelection->SelectLine();
			BSTR bstrLineText;
			hr = pTextSelection->get_Text(&bstrLineText);
			if (SUCCEEDED(hr))
			{
				s = bstrLineText;
				ts = s;
				ts.TrimLeft();
				if (ts == "")
					continue;

				if (ts.GetLength() <2)
					continue ;

				if (ts[0]=='/' && ts[1] =='/')
				{
					pTextSelection->Cancel();
					return S_OK;
					//int i = s.Find('/');
					//s.Delete(i,2);
					//pTextSelection->put_Text(s.AllocSysString());
				}
			}
		}
	}
	pTextSelection->Cancel();
	return S_FALSE;

}


STDMETHODIMP CCommands::CommentCodeN()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));

	HRESULT hr ;

	hr = GetTextSelection(m_pApplication);
	if (!SUCCEEDED(hr))
	{
		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
		m_pTextselect = NULL;
		return E_FAIL;
	}
	hr = CommentSelectedCodeN(m_pTextselect);
	if (!SUCCEEDED(hr))
	{
		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
		m_pTextselect = NULL;
		return E_FAIL;
	}

	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
	m_pTextselect = NULL;

	return S_OK;
}

STDMETHODIMP CCommands::UncommentCodeN()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
	
	HRESULT hr = GetTextSelection(m_pApplication);
	if (!SUCCEEDED(hr))
	{
		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
		m_pTextselect = NULL;
		return S_OK;
	}

	hr = UnCommentSelectedCodeN(m_pTextselect);
	if (!SUCCEEDED(hr))
	{
		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
		m_pTextselect = NULL;
		return E_FAIL;
	}

	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
	m_pTextselect = NULL;

	return S_OK;
}

HRESULT CCommands::CommentSelectedCodeN(IDispatch *pTextSel)
{
	long lTopLine = -1;
	long lBottomLine = -1;

	CString s;

	CComQIPtr<ITextSelection, &IID_ITextSelection> 
		pTextSelection(pTextSel);

	////////////////////////////
	HRESULT hr = pTextSelection->get_TopLine(&lTopLine);
	////////////////////////////
	hr = pTextSelection->get_BottomLine(&lBottomLine);
	_variant_t v((long)dsMove);

	////////////////////////////
	hr = pTextSelection->MoveTo(lTopLine, 1, v);
	if (SUCCEEDED(hr))
	{
		pTextSelection->SelectLine();
		BSTR bstrLineText;
		
		hr = pTextSelection->get_Text(&bstrLineText);
		if (SUCCEEDED(hr))
		{
			s = bstrLineText;
			s = _T("/*") + s;
			pTextSelection->put_Text(s.AllocSysString());
		}
		else
			return S_FALSE;
	}
	else
		return S_FALSE;


	////////////////////////////
	hr = pTextSelection->MoveTo(lBottomLine, 1, v);
	if (SUCCEEDED(hr))
	{
		pTextSelection->SelectLine();
		BSTR bstrLineText;
		
		hr = pTextSelection->get_Text(&bstrLineText);
		if (SUCCEEDED(hr))
		{
			s = bstrLineText;
//			if (s.GetLength() <= 4)
//				s = s+"*/";
//			else
				s.Insert(s.GetLength()-2,"*/");
			pTextSelection->put_Text(s.AllocSysString());
		}
		else
			return S_FALSE;
	}
	else
		return S_FALSE;


	pTextSelection->Cancel();
	return S_OK;

}

HRESULT CCommands::UnCommentSelectedCodeN(IDispatch *pTextSel)
{
	long lTopLine = -1;
	long lBottomLine = -1;

	CString s;
	CString ts;
	int i;

	CComQIPtr<ITextSelection, &IID_ITextSelection> 
		pTextSelection(pTextSel);

	////////////////////////////
	HRESULT hr = pTextSelection->get_TopLine(&lTopLine);
	////////////////////////////
	hr = pTextSelection->get_BottomLine(&lBottomLine);
	_variant_t v((long)dsMove);
	
	////////////////////////////
	hr = pTextSelection->MoveTo(lTopLine, 1, v);
	if (SUCCEEDED(hr))
	{
		pTextSelection->SelectLine();
		BSTR bstrLineText;
		hr = pTextSelection->get_Text(&bstrLineText);
		if (SUCCEEDED(hr))
		{
			s = bstrLineText;
			ts = s;
			ts.TrimLeft();
			if (ts == "")
				return S_FALSE;

			if (ts.GetLength() <2)
				return S_FALSE;

			if (ts[0]=='/' && ts[1] =='*')
			{
				i = s.Find('/');
				s.Delete(i,2);
				pTextSelection->put_Text(s.AllocSysString());
			}
		}
		else
			return S_FALSE;
	}
	else
		return S_FALSE;

	////////////////////////////
	hr = pTextSelection->MoveTo(lBottomLine, 1, v);
	if (SUCCEEDED(hr))
	{
		pTextSelection->SelectLine();
		BSTR bstrLineText;
		hr = pTextSelection->get_Text(&bstrLineText);
		if (SUCCEEDED(hr))
		{
			ts = bstrLineText;
			if (ts == "")
				return S_FALSE;

			if (ts.GetLength()<2)
				return S_FALSE;

			if (ts.GetLength() >= 4)
			{
				if (ts[ts.GetLength()-3]=='/' && ts[ts.GetLength()-4] =='*')
				{
					ts.Delete(ts.GetLength()-4,2);
				}
			}
			else
			{
				if (ts[ts.GetLength()-1]=='/' && ts[ts.GetLength()-2] =='*')
				{
					ts.Delete(ts.GetLength()-2,2);
				}
			}
			pTextSelection->put_Text(ts.AllocSysString());
		}
		else
			return S_FALSE;
	}
	else
		return S_FALSE;


	pTextSelection->Cancel();
	return S_OK;

}


//STDMETHODIMP CCommands::CopyTextToFile()
//{
//	AFX_MANAGE_STATE(AfxGetStaticModuleState())

//	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));

//	HRESULT hr ;

//	hr = GetTextSelection(m_pApplication);
//	if (!SUCCEEDED(hr))
//	{
//		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
//		m_pTextselect = NULL;
//		return E_FAIL;
//	}
//	hr = SaveTextToFile(m_pTextselect);
//	if (!SUCCEEDED(hr))
//	{
//		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
//		m_pTextselect = NULL;
//		return E_FAIL;
//	}

//	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
//	m_pTextselect = NULL;
//	return S_OK;
//}

HRESULT CCommands::SaveTextToFile(IDispatch *pTextSel)
{
	CString seltext;
	BSTR bstrLineText;

	CComQIPtr<ITextSelection, &IID_ITextSelection> 
		pTextSelection(pTextSel);

	FILE *f ;
			
	HRESULT hr = pTextSelection->get_Text(&bstrLineText);
	if (SUCCEEDED(hr))
	{
		seltext = bstrLineText;
		if (seltext == "")
			return E_FAIL;
		CFileDialog FileDlg(FALSE, "*.cpp", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szSaveFilter);
		if (FileDlg.DoModal() == IDOK)
		{
			CString fs  = FileDlg.GetPathName();
			f = fopen(fs,"wb");
			if (f == NULL)
				return E_FAIL;
			fwrite(seltext.GetBuffer(seltext.GetLength()),sizeof(char),seltext.GetLength(),f);
			fclose(f);
		}
		
	}
	else
		return E_FAIL;

	return S_OK;


}

////////////////////////////
//STDMETHODIMP CCommands::AddCodeComment()
//{
//	AFX_MANAGE_STATE(AfxGetStaticModuleState())

//	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));

//	HRESULT hr ;

//	hr = GetTextSelection(m_pApplication);
//	if (!SUCCEEDED(hr))
//	{
//		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
//		m_pTextselect = NULL;
//		return E_FAIL;
//	}
	
//	hr = PutCodeComment(m_pTextselect);
//	if (!SUCCEEDED(hr))
//	{
//		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
//		m_pTextselect = NULL;
//		return E_FAIL;
//	}

//	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
//	m_pTextselect = NULL;

//	return S_OK;
//}

//HRESULT CCommands::PutCodeComment(IDispatch *pTextSel)
//{
//	CComQIPtr<ITextSelection, &IID_ITextSelection> 
//		pTextSelection(pTextSel);

///*	CComDlg mdlg;
//	if (mdlg.DoModal() == IDOK)
//	{
//		HRESULT hr = pTextSelection->put_Text(mdlg.m_comment.AllocSysString());
//		if (!SUCCEEDED(hr))
//			return E_FAIL;
//	}
//	else
//		return E_FAIL;
//*/
//	return S_OK;

//}

//STDMETHODIMP CCommands::LoadCodeFromFile()
//{
//	AFX_MANAGE_STATE(AfxGetStaticModuleState())

//	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));

//	HRESULT hr ;

//	hr = GetTextSelection(m_pApplication);
//	if (!SUCCEEDED(hr))
//	{
//		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
//		m_pTextselect = NULL;
//		return E_FAIL;
//	}
	
//	hr =LoadTextFromFile(m_pTextselect);

//	if (!SUCCEEDED(hr))
//	{
//		VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
//		m_pTextselect = NULL;
//		return E_FAIL;
//	}

//	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
//	m_pTextselect = NULL;

//	return S_OK;

//}

HRESULT CCommands::LoadTextFromFile(IDispatch *pTextSel)
{
	long lTopLine = -1;
	CString s;
	FILE * file;
	int i;
	char buf[256];

	CFileDialog FileDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szSaveFilter);
	if (FileDlg.DoModal() == IDOK)
	{
		CComQIPtr<ITextSelection, &IID_ITextSelection> 
			pTextSelection(pTextSel);
		if ((file = fopen(FileDlg.GetPathName(),"r")) != NULL)
		{
			while(!feof(file))
			{
				memset(buf,0,256);
				i = fread(buf,1,256,file);
				if (i<=0 )
					break;
				s = s+buf;
			}
			fclose(file);
			HRESULT hr = pTextSelection->put_Text(s.AllocSysString());
			if (!SUCCEEDED(hr))
				return E_FAIL;
		}
		else
			return S_FALSE;
	}
	return S_OK;
}







/******************************************************************************
 ******************************************************************************
 * new added                                                                  *
 *                                                                            *
 * Dec 27 , 2009                                                              *
 *                                                                            *
 ******************************************************************************
 ******************************************************************************/




STDMETHODIMP CCommands::Addif() 
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	if (!CheckForTextType())
	{
		::MessageBox(::GetActiveWindow(), "Cannot Execute Command.\n\nNo Valid Text Document Is Opened or Maybe Project Is Not Opened.", "Error" ,MB_OK | MB_ICONINFORMATION);
		return S_OK;

	}


	CComPtr<IDispatch> pDispatch1;
	VERIFY_OK(m_pApplication->get_Documents(&pDispatch1))
		CComQIPtr<IDocuments, &IID_IDocuments> pDocuments(pDispatch1);

	CComPtr<IDispatch> pDispatch2;
	VERIFY_OK(m_pApplication->get_ActiveDocument(&pDispatch2))
		CComQIPtr<ITextDocument, &IID_ITextDocument> pDocument(pDispatch2);

	CComPtr<IDispatch> pDispatch4;
	VERIFY_OK(pDocument->get_Selection(&pDispatch4));
	CComQIPtr<ITextSelection, &IID_ITextSelection> pSelection(pDispatch4);

	CComBSTR bstrName;
	pDocument->get_Name(&bstrName);
	CString docName(bstrName);

    CComBSTR bstrText;

	long startLine;
	long endLine;
    int  nCursorOffset = 0;

	pSelection->get_TopLine(&startLine);
	pSelection->get_BottomLine(&endLine);

	if (startLine > endLine)
	{
		int temp=endLine;
		endLine=startLine;
		startLine=temp;
	}

	pSelection->GoToLine(startLine,CComVariant(0));
	pSelection->MoveTo(endLine,0,CComVariant(1));
	pSelection->get_Text(&bstrText);

	CString selText(bstrText);

    // Find out the starting position of the first word
	pSelection->GoToLine(startLine,CComVariant(0));
	pSelection->SelectLine();
	pSelection->get_Text(&bstrText);

	CString replText;
	CString tmpLineText(bstrText);

    CString     spaces;
    if (tmpLineText.IsEmpty())
    {
        spaces.Empty();
    }
    else
    {
        int         posit = 0;
        while (TRUE)
        {
            if (tmpLineText.GetAt(posit) == '\t')
            {
                spaces += "    ";
            }
            else if (tmpLineText.GetAt(posit) == ' ')
            {
                spaces += " ";
            }
            else
                break;
            posit++;
        }
    }
   
    bool    fReplaceText = false;


        fReplaceText = true;
        replText = TemplateIf(spaces, selText, nCursorOffset);
      
//         fReplaceText = true;
//         replText = TemplateIfElse(spaces, selText, nCursorOffset);
//      
//         fReplaceText = true;
//         replText = TemplateWhile(spaces, selText, nCursorOffset);
    

	// Comment Utilities...

    bstrText = replText;

    pSelection->GoToLine(startLine, CComVariant(dsMove));
    if (fReplaceText)
    {
        pSelection->MoveTo(endLine, 0, CComVariant(dsExtend));
    }
    pSelection->put_Text(bstrText);

    pSelection->GoToLine(startLine,CComVariant(dsMove));
    pSelection->CharRight(CComVariant(dsMove), CComVariant(nCursorOffset));

	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));

    m_working = FALSE;

	return S_OK;
}
STDMETHODIMP CCommands::Addifelse() 
{


	// TODO: Replace this with the actual code to execute this command
	//  Use m_pApplication to access the Developer Studio Application object,
	//  and VERIFY_OK to see error strings in DEBUG builds of your add-in
	//  (see stdafx.h)

	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	if (!CheckForTextType())
	{
		::MessageBox(::GetActiveWindow(), "Cannot Execute Command.\n\nNo Valid Text Document Is Opened or Maybe Project Is Not Opened.", "Error" ,MB_OK | MB_ICONINFORMATION);
		return S_OK;

	}


	CComPtr<IDispatch> pDispatch1;
	VERIFY_OK(m_pApplication->get_Documents(&pDispatch1))
		CComQIPtr<IDocuments, &IID_IDocuments> pDocuments(pDispatch1);

	CComPtr<IDispatch> pDispatch2;
	VERIFY_OK(m_pApplication->get_ActiveDocument(&pDispatch2))
		CComQIPtr<ITextDocument, &IID_ITextDocument> pDocument(pDispatch2);

	CComPtr<IDispatch> pDispatch4;
	VERIFY_OK(pDocument->get_Selection(&pDispatch4));
	CComQIPtr<ITextSelection, &IID_ITextSelection> pSelection(pDispatch4);

	CComBSTR bstrName;
	pDocument->get_Name(&bstrName);
	CString docName(bstrName);

    CComBSTR bstrText;

	long startLine;
	long endLine;
    int  nCursorOffset = 0;

	pSelection->get_TopLine(&startLine);
	pSelection->get_BottomLine(&endLine);

	if (startLine > endLine)
	{
		int temp=endLine;
		endLine=startLine;
		startLine=temp;
	}

	pSelection->GoToLine(startLine,CComVariant(0));
	pSelection->MoveTo(endLine,0,CComVariant(1));
	pSelection->get_Text(&bstrText);

	CString selText(bstrText);

    // Find out the starting position of the first word
	pSelection->GoToLine(startLine,CComVariant(0));
	pSelection->SelectLine();
	pSelection->get_Text(&bstrText);

	CString replText;
	CString tmpLineText(bstrText);

    CString     spaces;
    if (tmpLineText.IsEmpty())
    {
        spaces.Empty();
    }
    else
    {
        int         posit = 0;
        while (TRUE)
        {
            if (tmpLineText.GetAt(posit) == '\t')
            {
                spaces += "    ";
            }
            else if (tmpLineText.GetAt(posit) == ' ')
            {
                spaces += " ";
            }
            else
                break;
            posit++;
        }
    }
   
    bool    fReplaceText = false;


//         fReplaceText = true;
//         replText = TemplateIf(spaces, selText, nCursorOffset);
      
        fReplaceText = true;
        replText = TemplateIfElse(spaces, selText, nCursorOffset);
//      
//         fReplaceText = true;
//         replText = TemplateWhile(spaces, selText, nCursorOffset);
    

	// Comment Utilities...

    bstrText = replText;

    pSelection->GoToLine(startLine, CComVariant(dsMove));
    if (fReplaceText)
    {
        pSelection->MoveTo(endLine, 0, CComVariant(dsExtend));
    }
    pSelection->put_Text(bstrText);

    pSelection->GoToLine(startLine,CComVariant(dsMove));
    pSelection->CharRight(CComVariant(dsMove), CComVariant(nCursorOffset));

	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));

    m_working = FALSE;
	return S_OK;
}
STDMETHODIMP CCommands::Addwhile() 
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	if (!CheckForTextType())
	{
		::MessageBox(::GetActiveWindow(), "Cannot Execute Command.\n\nNo Valid Text Document Is Opened or Maybe Project Is Not Opened.", "Error" ,MB_OK | MB_ICONINFORMATION);
		return S_OK;

	}


	CComPtr<IDispatch> pDispatch1;
	VERIFY_OK(m_pApplication->get_Documents(&pDispatch1))
		CComQIPtr<IDocuments, &IID_IDocuments> pDocuments(pDispatch1);

	CComPtr<IDispatch> pDispatch2;
	VERIFY_OK(m_pApplication->get_ActiveDocument(&pDispatch2))
		CComQIPtr<ITextDocument, &IID_ITextDocument> pDocument(pDispatch2);

	CComPtr<IDispatch> pDispatch4;
	VERIFY_OK(pDocument->get_Selection(&pDispatch4));
	CComQIPtr<ITextSelection, &IID_ITextSelection> pSelection(pDispatch4);

	CComBSTR bstrName;
	pDocument->get_Name(&bstrName);
	CString docName(bstrName);

    CComBSTR bstrText;

	long startLine;
	long endLine;
    int  nCursorOffset = 0;

	pSelection->get_TopLine(&startLine);
	pSelection->get_BottomLine(&endLine);

	if (startLine > endLine)
	{
		int temp=endLine;
		endLine=startLine;
		startLine=temp;
	}

	pSelection->GoToLine(startLine,CComVariant(0));
	pSelection->MoveTo(endLine,0,CComVariant(1));
	pSelection->get_Text(&bstrText);

	CString selText(bstrText);

    // Find out the starting position of the first word
	pSelection->GoToLine(startLine,CComVariant(0));
	pSelection->SelectLine();
	pSelection->get_Text(&bstrText);

	CString replText;
	CString tmpLineText(bstrText);

    CString     spaces;
    if (tmpLineText.IsEmpty())
    {
        spaces.Empty();
    }
    else
    {
        int         posit = 0;
        while (TRUE)
        {
            if (tmpLineText.GetAt(posit) == '\t')
            {
                spaces += "    ";
            }
            else if (tmpLineText.GetAt(posit) == ' ')
            {
                spaces += " ";
            }
            else
                break;
            posit++;
        }
    }
   
    bool    fReplaceText = false;


//         fReplaceText = true;
//         replText = TemplateIf(spaces, selText, nCursorOffset);
//       
//          fReplaceText = true;
//          replText = TemplateIfElse(spaces, selText, nCursorOffset);
//      
        fReplaceText = true;
        replText = TemplateWhile(spaces, selText, nCursorOffset);
    

	// Comment Utilities...

    bstrText = replText;

    pSelection->GoToLine(startLine, CComVariant(dsMove));
    if (fReplaceText)
    {
        pSelection->MoveTo(endLine, 0, CComVariant(dsExtend));
    }
    pSelection->put_Text(bstrText);

    pSelection->GoToLine(startLine,CComVariant(dsMove));
    pSelection->CharRight(CComVariant(dsMove), CComVariant(nCursorOffset));

	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));

    m_working = FALSE;
	return S_OK;
}
/******************************************************************************
 *                                                                            *
 * CCommands::TemplateIf                                                      *
 *                                                                            *
 * Aug 05, 2002                                                               *
 *                                                                            *
 *                                                                            *
 *                                                                            *
 ******************************************************************************/
CString
CCommands::TemplateIf(const CString & spaces,
                            CString & selText,
                            int     & nCursorOffset)
{
    CString     replText;

    replText = spaces + "if ( ";

    // Save the position where we want the cursor
    nCursorOffset = replText.GetLength();

    replText += " )\n" + spaces + "{\n";

	int         pos = 0;
    selText.Insert(pos, "    ");
    while (1)
    {
        pos = selText.Find("\n", pos + 2);

        if (pos < 0)
            break;
        selText.Insert(pos + 1, "    ");
    }
    replText += selText + "\n";
    replText += spaces + "}";

    // Return to caller.
    return replText;

}   // CCommands::TemplateIf()


/******************************************************************************
 *                                                                            *
 * CCommands::TemplateIfElse                                                  *
 *                                                                            *
 * Aug 05, 2002                                                               *
 *                                                                            *
 *                                                                            *
 *                                                                            *
 ******************************************************************************/
CString
CCommands::TemplateIfElse(const CString & spaces,
                                CString & selText,
                                int     & nCursorOffset)
{
    CString     replText;

    replText  = spaces + "if ( ";

    // Save the position where we want the cursor
    nCursorOffset = replText.GetLength();

    replText += " )\n";
    replText += spaces + "{\n";

	int         pos = 0;
    selText.Insert(pos, "    ");
    while (1)
    {
        pos = selText.Find("\n", pos + 2);

        if (pos < 0)
            break;
        selText.Insert(pos + 1, "    ");
    }
    replText += selText + "\n" + spaces + "}\n";
    replText += spaces + "else\n";
    replText += spaces + "{\n";
    replText += spaces + "\n";
    replText += spaces + "}";

    // Return to caller.
    return replText;

}   // CCommands::TemplateIfElse()

CString
CCommands::TemplateWhile(const CString & spaces,
                               CString & selText,
                               int     & nCursorOffset)
{
    CString     replText;

    replText  = spaces + "while ( ";

    // Save the position where we want the cursor
    nCursorOffset = replText.GetLength();

    replText += " )\n";
    replText += spaces + "{\n";

	int         pos = 0;
    selText.Insert(pos, "    ");
    while (1)
    {
        pos = selText.Find("\n", pos + 2);

        if (pos < 0)
            break;
        selText.Insert(pos + 1, "    ");
    }
    replText += selText + "\n";
    replText += spaces + "}";

    // Return to caller.
    return replText;

}   // CCommands::TemplateWhile() 




BOOL CCommands::CheckForTextType()
{
	CComPtr<IDispatch> pDispatch1;
	m_pApplication->get_Documents(&pDispatch1);
	CComQIPtr<IDocuments, &IID_IDocuments> pDocuments(pDispatch1);


	long l=0;
	pDocuments->get_Count(&l);

	CString cs;
	cs.Format("%d",l);

	//AfxMessageBox(cs);
	if (l<1)
	{
		return FALSE;
	}

	IGenericDocument* pDoc;
	m_pApplication->get_ActiveDocument((IDispatch**)&pDoc);
	BSTR bstrType;
	pDoc->get_Type(&bstrType);
	if (!wcscmp(bstrType, L"Text"))
	{
		SysFreeString(bstrType);
		pDoc->Release();
		return TRUE;
	}
	else
	{
		SysFreeString(bstrType);
		pDoc->Release();
		return FALSE;
	}


} 